/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.facebook.fresco.helper;

import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.Image;
import ohos.agp.components.element.PixelMapElement;
import ohos.app.Context;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.PixelFormat;
import ohos.utils.net.Uri;

import com.facebook.common.executors.UiThreadImmediateExecutorService;
import com.facebook.common.memory.PooledByteBuffer;
import com.facebook.common.memory.PooledByteBufferInputStream;
import com.facebook.common.references.CloseableReference;
import com.facebook.common.util.UriUtil;
import com.facebook.datasource.BaseDataSubscriber;
import com.facebook.datasource.DataSource;
import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.drawee.backends.pipeline.PipelineDraweeControllerBuilder;
import com.facebook.drawee.controller.BaseControllerListener;
import com.facebook.drawee.controller.ControllerListener;
import com.facebook.drawee.drawable.Animatable;
import com.facebook.drawee.interfaces.DraweeController;
import com.facebook.drawee.view.SimpleDraweeView;
import com.facebook.fresco.helper.blur.BitmapBlurHelper;
import com.facebook.fresco.helper.listener.IDownloadResult;
import com.facebook.fresco.helper.listener.IResult;
import com.facebook.fresco.helper.utils.MLog;
import com.facebook.fresco.helper.utils.StreamTool;
import com.facebook.imagepipeline.animated.base.AnimatedImageResult;
import com.facebook.imagepipeline.common.ResizeOptions;
import com.facebook.imagepipeline.common.RotationOptions;
import com.facebook.imagepipeline.core.ImagePipeline;
import com.facebook.imagepipeline.image.CloseableAnimatedImage;
import com.facebook.imagepipeline.image.CloseableBitmap;
import com.facebook.imagepipeline.image.CloseableImage;
import com.facebook.imagepipeline.image.ImageInfo;
import com.facebook.imagepipeline.request.BasePostprocessor;
import com.facebook.imagepipeline.request.ImageRequest;
import com.facebook.imagepipeline.request.ImageRequestBuilder;
import com.oszc.bbhmlibrary.wrapper.TextUtils;

import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
 * 提供基于Fresco的图片加载工具类
 *
 * @since 2021-07-29
 */
public class ImageLoader {
    private ImageLoader() {
    }

    /**
     * 加载图片
     *
     * @param simpleDraweeView 简单的付款人视图
     * @param url url
     */
    public static void loadImage(SimpleDraweeView simpleDraweeView, String url) {
        if (TextUtils.isEmpty(url) || simpleDraweeView == null) {
            return;
        }
        Uri uri = Uri.parse(url);
        loadImage(simpleDraweeView, uri, 0, 0, null, null, false);
    }

    /**
     * 加载图片
     *
     * @param simpleDraweeView 简单的付款人视图
     * @param url url
     * @param reqWidth 要求的宽度
     * @param reqHeight 要求的高度
     */
    public static void loadImage(SimpleDraweeView simpleDraweeView, String url, int reqWidth, int reqHeight) {
        if (TextUtils.isEmpty(url) || simpleDraweeView == null) {
            return;
        }
        Uri uri = Uri.parse(url);
        loadImage(simpleDraweeView, uri, reqWidth, reqHeight, null, null, false);
    }

    /**
     * 加载图片
     *
     * @param simpleDraweeView 简单的付款人视图
     * @param url url
     * @param processor 处理器
     */
    public static void loadImage(SimpleDraweeView simpleDraweeView, String url, BasePostprocessor processor) {
        if (TextUtils.isEmpty(url) || simpleDraweeView == null) {
            return;
        }
        Uri uri = Uri.parse(url);
        loadImage(simpleDraweeView, uri, 0, 0, processor, null, false);
    }

    /**
     * 加载图片
     *
     * @param simpleDraweeView 简单的付款人视图
     * @param url url
     * @param reqWidth 要求的宽度
     * @param reqHeight 要求的高度
     * @param processor 处理器
     */
    public static void loadImage(SimpleDraweeView simpleDraweeView, String url,
                                 int reqWidth, int reqHeight, BasePostprocessor processor) {
        if (TextUtils.isEmpty(url) || simpleDraweeView == null) {
            return;
        }
        Uri uri = Uri.parse(url);
        loadImage(simpleDraweeView, uri, reqWidth, reqHeight, processor, null, false);
    }

    /**
     * 加载图片
     *
     * @param simpleDraweeView 简单的付款人视图
     * @param url url
     * @param controllerListener 控制器监听器
     */
    public static void loadImage(SimpleDraweeView simpleDraweeView, String url,
                                 ControllerListener<ImageInfo> controllerListener) {
        if (TextUtils.isEmpty(url) || simpleDraweeView == null) {
            return;
        }
        Uri uri = Uri.parse(url);
        loadImage(simpleDraweeView, uri, 0, 0, null, controllerListener, false);
    }

    /**
     * 加载图片
     *
     * @param simpleDraweeView 简单的付款人视图
     * @param uri uri
     * @param reqWidth 要求的宽度
     * @param reqHeight 要求的高度
     * @param postprocessor 后处理程序
     * @param controllerListener 控制器监听器
     * @param isSmall 小
     */
    public static void loadImage(SimpleDraweeView simpleDraweeView, Uri uri, int reqWidth,
                                 int reqHeight, BasePostprocessor postprocessor,
                                 ControllerListener<ImageInfo> controllerListener, boolean isSmall) {
        ImageRequestBuilder imageRequestBuilder = ImageRequestBuilder.newBuilderWithSource(uri);
        imageRequestBuilder.setRotationOptions(RotationOptions.autoRotate());

        // 不支持图片渐进式加载
        imageRequestBuilder.setProgressiveRenderingEnabled(false);
        if (isSmall) {
            imageRequestBuilder.setCacheChoice(ImageRequest.CacheChoice.SMALL);
        }
        if (reqWidth > 0 && reqHeight > 0) {
            imageRequestBuilder.setResizeOptions(new ResizeOptions(reqWidth, reqHeight));
        }
        if (UriUtil.isLocalFileUri(uri)) {
            imageRequestBuilder.setLocalThumbnailPreviewsEnabled(true);
        }
        if (postprocessor != null) {
            imageRequestBuilder.setPostprocessor(postprocessor);
        }
        ImageRequest imageRequest = imageRequestBuilder.build();
        PipelineDraweeControllerBuilder draweeControllerBuilder = Fresco.newDraweeControllerBuilder();
        draweeControllerBuilder.setOldController(simpleDraweeView.getController());
        draweeControllerBuilder.setImageRequest(imageRequest);

        if (controllerListener != null) {
            draweeControllerBuilder.setControllerListener(controllerListener);
        }
        draweeControllerBuilder.setTapToRetryEnabled(false); // 在加载失败后，禁用点击重试功能
        draweeControllerBuilder.setAutoPlayAnimations(true); // 自动播放gif动画
        DraweeController draweeController = draweeControllerBuilder.build();
        simpleDraweeView.setController(draweeController);
    }

    /**
     * 根据提供的图片URL加载原始图（该方法仅针对大小在100k以内的图片，若不确定图片大小
     *
     * @param context 上下文
     * @param url url
     * @param loadImageResult 加载图像结果
     */
    public static void loadImage(Context context, String url, IResult<PixelMap> loadImageResult) {
        loadOriginalImage(context, url, loadImageResult, UiThreadImmediateExecutorService.getInstance());
    }

    /**
     * 加载图片
     *
     * @param context 上下文
     * @param url url
     * @param reqWidth 要求的宽度
     * @param reqHeight 要求的高度
     * @param loadImageResult 加载图像结果
     */
    public static void loadImage(Context context, String url, int reqWidth, int reqHeight,
                                 IResult<PixelMap> loadImageResult) {
        if (TextUtils.isEmpty(url)) {
            return;
        }
        Uri uri = Uri.parse(url);
        ImagePipeline imagePipeline = Fresco.getImagePipeline();
        ImageRequestBuilder imageRequestBuilder = ImageRequestBuilder.newBuilderWithSource(uri);
        if (reqWidth > 0 && reqHeight > 0) {
            imageRequestBuilder.setResizeOptions(new ResizeOptions(reqWidth, reqHeight));
        }
        ImageRequest imageRequest = imageRequestBuilder.build();

        // 获取已解码的图片，返回的是Bitmap
        DataSource<CloseableReference<CloseableImage>> dataSource = imagePipeline
            .fetchDecodedImage(imageRequest, context);
        dataSource.subscribe(new BaseDataSubscriber<CloseableReference<CloseableImage>>() {
            @Override
            public void onNewResultImpl(DataSource<CloseableReference<CloseableImage>> dataSource) {
                if (!dataSource.isFinished()) {
                    return;
                }
                disposePixelMapDataSource(dataSource, loadImageResult);
            }

            @Override
            public void onProgressUpdate(DataSource<CloseableReference<CloseableImage>> dataSource) {
                int progress = (int) (dataSource.getProgress() * 100);
                if (loadImageResult != null) {
                    loadImageResult.onProgress(progress);
                }
            }

            @Override
            public void onFailureImpl(DataSource dataSource) {
                if (loadImageResult != null) {
                    loadImageResult.onResult(null);
                }

                Throwable throwable = dataSource.getFailureCause();
                if (throwable != null) {
                    MLog.error("ImageLoader", "onFailureImpl = " + throwable.toString());
                }
            }
        }, UiThreadImmediateExecutorService.getInstance());
    }

    private static void disposePixelMapDataSource(DataSource<CloseableReference<CloseableImage>> dataSource,
                                                  IResult<PixelMap> loadImageResult) {
        CloseableReference<CloseableImage> imageReference = dataSource.getResult();
        if (imageReference != null) {
            CloseableReference<CloseableImage> closeableReference = imageReference.clone();
            try {
                setPixelMap2(loadImageResult, closeableReference);
            } finally {
                imageReference.close();
                closeableReference.close();
            }
        }
    }

    private static void setPixelMap2(IResult<PixelMap> loadImageResult,
                                     CloseableReference<CloseableImage> closeableReference) {
        CloseableImage closeableImage = closeableReference.get();
        if (closeableImage instanceof CloseableAnimatedImage) {
            AnimatedImageResult animatedImageResult = ((CloseableAnimatedImage) closeableImage).getImageResult();
            if (animatedImageResult != null && animatedImageResult.getImage() != null) {
                int imageWidth = animatedImageResult.getImage().getWidth();
                int imageHeight = animatedImageResult.getImage().getHeight();

                ImageSource.DecodingOptions options = new ImageSource.DecodingOptions();
                options.desiredSize.width = imageWidth;
                options.desiredSize.height = imageHeight;
                options.desiredPixelFormat = PixelFormat.ARGB_8888;
                ImageSource imageSource = ImageSource.createIncrementalSource(new ImageSource.SourceOptions());
                PixelMap bitmap = imageSource.createPixelmap(options);

                animatedImageResult.getImage().getFrame(0).renderFrame(imageWidth, imageHeight, bitmap);
                if (loadImageResult != null) {
                    loadImageResult.onResult(bitmap);
                }
            }
        } else if (closeableImage instanceof CloseableBitmap) {
            CloseableBitmap closeableBitmap = (CloseableBitmap) closeableImage;
            PixelMap bitmap = closeableBitmap.getUnderlyingBitmap();
            if (bitmap != null && !bitmap.isReleased()) {
                PixelMap tempBitmap = PixelMap.create(bitmap, new PixelMap.InitializationOptions());
                if (loadImageResult != null) {
                    loadImageResult.onResult(tempBitmap);
                }
            }
        }
    }

    /**
     * 加载图像小
     *
     * @param simpleDraweeView 简单的付款人视图
     * @param url url
     */
    public static void loadImageSmall(SimpleDraweeView simpleDraweeView, String url) {
        if (TextUtils.isEmpty(url) || simpleDraweeView == null) {
            return;
        }
        Uri uri = Uri.parse(url);
        loadImage(simpleDraweeView, uri, 0, 0, null, null, true);
    }

    /**
     * 加载图像小
     *
     * @param simpleDraweeView 简单的付款人视图
     * @param url url
     * @param reqWidth 要求的宽度
     * @param reqHeight 要求的高度
     */
    public static void loadImageSmall(SimpleDraweeView simpleDraweeView, String url, int reqWidth, int reqHeight) {
        if (TextUtils.isEmpty(url) || simpleDraweeView == null) {
            return;
        }
        Uri uri = Uri.parse(url);
        loadImage(simpleDraweeView, uri, reqWidth, reqHeight, null, null, true);
    }

    /**
     * 加载图像小
     *
     * @param simpleDraweeView 简单的付款人视图
     * @param url url
     * @param processor 处理器
     */
    public static void loadImageSmall(SimpleDraweeView simpleDraweeView, String url, BasePostprocessor processor) {
        if (TextUtils.isEmpty(url) || simpleDraweeView == null) {
            return;
        }
        Uri uri = Uri.parse(url);
        loadImage(simpleDraweeView, uri, 0, 0, processor, null, true);
    }

    /**
     * 加载图像小
     *
     * @param simpleDraweeView 简单的付款人视图
     * @param url url
     * @param reqWidth 要求的宽度
     * @param reqHeight 要求的高度
     * @param processor 处理器
     */
    public static void loadImageSmall(SimpleDraweeView simpleDraweeView, String url,
                                      int reqWidth, int reqHeight, BasePostprocessor processor) {
        if (TextUtils.isEmpty(url) || simpleDraweeView == null) {
            return;
        }
        Uri uri = Uri.parse(url);
        loadImage(simpleDraweeView, uri, reqWidth, reqHeight, processor, null, true);
    }

    /**
     * 加载文件
     *
     * @param simpleDraweeView 简单的付款人视图
     * @param filePath 文件路径
     */
    public static void loadFile(SimpleDraweeView simpleDraweeView, String filePath) {
        if (TextUtils.isEmpty(filePath)) {
            return;
        }
        Uri uri = new Uri.Builder().scheme(UriUtil.LOCAL_FILE_SCHEME).decodedPath(filePath).build();
        loadImage(simpleDraweeView, uri, 0, 0, null, null, false);
    }

    /**
     * 加载文件
     *
     * @param simpleDraweeView 简单的付款人视图
     * @param filePath 文件路径
     * @param reqWidth 要求的宽度
     * @param reqHeight 要求的高度
     */
    public static void loadFile(SimpleDraweeView simpleDraweeView, String filePath, int reqWidth, int reqHeight) {
        if (TextUtils.isEmpty(filePath)) {
            return;
        }
        Uri uri = new Uri.Builder().scheme(UriUtil.LOCAL_FILE_SCHEME).decodedPath(filePath).build();
        BaseControllerListener<ImageInfo> controllerListener = new BaseControllerListener<ImageInfo>() {
            @Override
            public void onFinalImageSet(String id, ImageInfo imageInfo, Animatable anim) {
                if (imageInfo == null) {
                    return;
                }

                ComponentContainer.LayoutConfig vp = simpleDraweeView.getLayoutConfig();
                vp.width = reqWidth;
                vp.height = reqHeight;
                simpleDraweeView.postLayout();
            }
        };
        loadImage(simpleDraweeView, uri, reqWidth, reqHeight, null, controllerListener, false);
    }

    /**
     * 加载文件
     *
     * @param simpleDraweeView 简单的付款人视图
     * @param filePath 文件路径
     * @param processor 处理器
     */
    public static void loadFile(SimpleDraweeView simpleDraweeView, String filePath, BasePostprocessor processor) {
        if (TextUtils.isEmpty(filePath)) {
            return;
        }
        Uri uri = new Uri.Builder().scheme(UriUtil.LOCAL_FILE_SCHEME).decodedPath(filePath).build();
        loadImage(simpleDraweeView, uri, 0, 0, processor, null, false);
    }

    /**
     * 加载文件
     *
     * @param simpleDraweeView 简单的付款人视图
     * @param filePath 文件路径
     * @param reqWidth 要求的宽度
     * @param reqHeight 要求的高度
     * @param processor 处理器
     */
    public static void loadFile(SimpleDraweeView simpleDraweeView, String filePath,
                                int reqWidth, int reqHeight, BasePostprocessor processor) {
        if (TextUtils.isEmpty(filePath)) {
            return;
        }
        Uri uri = new Uri.Builder().scheme(UriUtil.LOCAL_FILE_SCHEME).decodedPath(filePath).build();
        loadImage(simpleDraweeView, uri, reqWidth, reqHeight, processor, null, false);
    }

    /**
     * 可拉的负载
     *
     * @param simpleDraweeView 简单的付款人视图
     * @param resId res id
     */
    public static void loadDrawable(SimpleDraweeView simpleDraweeView, int resId) {
        if (resId == 0 || simpleDraweeView == null) {
            return;
        }
        Uri uri = new Uri.Builder().scheme(UriUtil.LOCAL_RESOURCE_SCHEME).decodedPath(String.valueOf(resId)).build();
        loadImage(simpleDraweeView, uri, 0, 0, null, null, false);
    }

    /**
     * 可拉的负载
     *
     * @param simpleDraweeView 简单的付款人视图
     * @param resId res id
     * @param reqWidth 要求的宽度
     * @param reqHeight 要求的高度
     */
    public static void loadDrawable(SimpleDraweeView simpleDraweeView, int resId, int reqWidth, int reqHeight) {
        if (resId == 0 || simpleDraweeView == null) {
            return;
        }
        Uri uri = new Uri.Builder().scheme(UriUtil.LOCAL_RESOURCE_SCHEME).decodedPath(String.valueOf(resId)).build();
        loadImage(simpleDraweeView, uri, reqWidth, reqHeight, null, null, false);
    }

    /**
     * 可拉的负载
     *
     * @param simpleDraweeView 简单的付款人视图
     * @param resId res id
     * @param processor 处理器
     */
    public static void loadDrawable(SimpleDraweeView simpleDraweeView, int resId, BasePostprocessor processor) {
        if (resId == 0 || simpleDraweeView == null) {
            return;
        }

        Uri uri = new Uri.Builder().scheme(UriUtil.LOCAL_RESOURCE_SCHEME).decodedPath(String.valueOf(resId)).build();
        loadImage(simpleDraweeView, uri, 0, 0, processor, null, false);
    }

    /**
     * 可拉的负载
     *
     * @param simpleDraweeView 简单的付款人视图
     * @param resId res id
     * @param reqWidth 要求的宽度
     * @param reqHeight 要求的高度
     * @param processor 处理器
     */
    public static void loadDrawable(SimpleDraweeView simpleDraweeView, int resId,
                                    int reqWidth, int reqHeight, BasePostprocessor processor) {
        if (resId == 0 || simpleDraweeView == null) {
            return;
        }

        Uri uri = new Uri.Builder().scheme(UriUtil.LOCAL_RESOURCE_SCHEME).decodedPath(String.valueOf(resId)).build();
        loadImage(simpleDraweeView, uri, reqWidth, reqHeight, processor, null, false);
    }

    /**
     * 资产可拉的负载
     *
     * @param simpleDraweeView 简单的付款人视图
     * @param filename 文件名
     */
    public static void loadAssetDrawable(SimpleDraweeView simpleDraweeView, String filename) {
        if (filename == null || simpleDraweeView == null) {
            return;
        }
        Uri uri = new Uri.Builder().scheme(UriUtil.LOCAL_ASSET_SCHEME).decodedPath(filename).build();
        loadImage(simpleDraweeView, uri, 0, 0, null, null, false);
    }

    /**
     * 资产可拉的负载
     *
     * @param simpleDraweeView 简单的付款人视图
     * @param filename 文件名
     * @param reqWidth 要求的宽度
     * @param reqHeight 要求的高度
     */
    public static void loadAssetDrawable(SimpleDraweeView simpleDraweeView,
                                         String filename, int reqWidth, int reqHeight) {
        if (filename == null || simpleDraweeView == null) {
            return;
        }
        Uri uri = new Uri.Builder().scheme(UriUtil.LOCAL_ASSET_SCHEME).decodedPath(filename).build();
        loadImage(simpleDraweeView, uri, reqWidth, reqHeight, null, null, false);
    }

    /**
     * 资产可拉的负载
     *
     * @param simpleDraweeView 简单的付款人视图
     * @param filename 文件名
     * @param processor 处理器
     */
    public static void loadAssetDrawable(SimpleDraweeView simpleDraweeView,
                                         String filename, BasePostprocessor processor) {
        if (filename == null || simpleDraweeView == null) {
            return;
        }
        Uri uri = new Uri.Builder().scheme(UriUtil.LOCAL_ASSET_SCHEME).decodedPath(filename).build();
        loadImage(simpleDraweeView, uri, 0, 0, processor, null, false);
    }

    /**
     * 资产可拉的负载
     *
     * @param simpleDraweeView 简单的付款人视图
     * @param filename 文件名
     * @param reqWidth 要求的宽度
     * @param reqHeight 要求的高度
     * @param processor 处理器
     */
    public static void loadAssetDrawable(SimpleDraweeView simpleDraweeView, String filename,
                                         int reqWidth, int reqHeight, BasePostprocessor processor) {
        if (filename == null || simpleDraweeView == null) {
            return;
        }
        Uri uri = new Uri.Builder().scheme(UriUtil.LOCAL_ASSET_SCHEME).decodedPath(filename).build();
        loadImage(simpleDraweeView, uri, reqWidth, reqHeight, processor, null, false);
    }

    /**
     * 加载图像模糊
     *
     * @param view 视图
     * @param url url
     */
    public static void loadImageBlur(Component view, String url) {
        if (view == null || TextUtils.isEmpty(url)) {
            return;
        }
        loadImage(view.getContext(), url, new IResult<PixelMap>() {
            @Override
            public void onResult(PixelMap result) {
                if (result == null) {
                    return;
                }
                PixelMap blurBitmap = BitmapBlurHelper.blur(view.getContext(), result);
                view.setBackground(new PixelMapElement(blurBitmap));
            }

            @Override
            public void onProgress(int progress) {
            }
        });
    }

    /**
     * 加载图像模糊
     *
     * @param view 视图
     * @param url url
     * @param reqWidth 要求的宽度
     * @param reqHeight 要求的高度
     */
    public static void loadImageBlur(Component view, String url, int reqWidth, int reqHeight) {
        loadImage(view.getContext(), url, reqWidth, reqHeight, new IResult<PixelMap>() {
            @Override
            public void onResult(PixelMap source) {
                if (source == null) {
                    return;
                }
                PixelMap blurBitmap = BitmapBlurHelper.blur(view.getContext(), source);
                view.setBackground(new PixelMapElement(blurBitmap));
            }

            @Override
            public void onProgress(int progress) {
            }
        });
    }

    /**
     * 加载图像模糊
     *
     * @param draweeView 付款人的观点
     * @param url url
     * @param image 图像
     */
    public static void loadImageBlur(Image image, SimpleDraweeView draweeView, String url) {
        loadImage(draweeView, url, new BasePostprocessor() {
            @Override
            public String getName() {
                return "blurPostprocessor";
            }

            @Override
            public void process(PixelMap bitmap) {
                if (bitmap == null) {
                    return;
                }
                PixelMap pixelMap = BitmapBlurHelper.blur2(bitmap, 35);
                image.setPixelMap(pixelMap);
            }
        });
    }

    /**
     * 加载图像模糊
     *
     * @param draweeView 付款人的观点
     * @param url url
     * @param reqWidth 要求的宽度
     * @param reqHeight 要求的高度
     */
    public static void loadImageBlur(SimpleDraweeView draweeView, String url, int reqWidth, int reqHeight) {
        loadImage(draweeView, url, reqWidth, reqHeight, new BasePostprocessor() {
            @Override
            public String getName() {
                return "blurPostprocessor";
            }

            @Override
            public void process(PixelMap bitmap) {
                if (bitmap == null) {
                    return;
                }
                BitmapBlurHelper.blur(bitmap, 35);
            }
        });
    }

    /**
     * 加载文件模糊
     *
     * @param draweeView 付款人的观点
     * @param filePath 文件路径
     */
    public static void loadFileBlur(SimpleDraweeView draweeView, String filePath) {
        loadFile(draweeView, filePath, new BasePostprocessor() {
            @Override
            public String getName() {
                return "blurPostprocessor";
            }

            @Override
            public void process(PixelMap bitmap) {
                if (bitmap == null) {
                    return;
                }
                BitmapBlurHelper.blur(bitmap, 35);
            }
        });
    }

    /**
     * 加载文件模糊
     *
     * @param draweeView 付款人的观点
     * @param filePath 文件路径
     * @param reqWidth 要求的宽度
     * @param reqHeight 要求的高度
     */
    public static void loadFileBlur(SimpleDraweeView draweeView, String filePath, int reqWidth, int reqHeight) {
        loadFile(draweeView, filePath, reqWidth, reqHeight, new BasePostprocessor() {
            @Override
            public String getName() {
                return "blurPostprocessor";
            }

            @Override
            public void process(PixelMap bitmap) {
                if (bitmap == null) {
                    return;
                }
                BitmapBlurHelper.blur(bitmap, 35);
            }
        });
    }

    /**
     * 负载可拉的模糊
     *
     * @param simpleDraweeView 简单的付款人视图
     * @param resId res id
     * @param reqWidth 要求的宽度
     * @param reqHeight 要求的高度
     */
    public static void loadDrawableBlur(SimpleDraweeView simpleDraweeView, int resId, int reqWidth, int reqHeight) {
        loadDrawable(simpleDraweeView, resId, reqWidth, reqHeight, new BasePostprocessor() {
            @Override
            public String getName() {
                return "blurPostprocessor";
            }

            @Override
            public void process(PixelMap bitmap) {
                if (bitmap == null) {
                    return;
                }
                BitmapBlurHelper.blur(bitmap, 35);
            }
        });
    }

    /**
     * 负载可拉的模糊
     *
     * @param simpleDraweeView 简单的付款人视图
     * @param resId res id
     */
    public static void loadDrawableBlur(SimpleDraweeView simpleDraweeView, int resId) {
        loadDrawable(simpleDraweeView, resId, new BasePostprocessor() {
            @Override
            public String getName() {
                return "blurPostprocessor";
            }

            @Override
            public void process(PixelMap bitmap) {
                if (bitmap == null) {
                    return;
                }
                BitmapBlurHelper.blur(bitmap, 35);
            }
        });
    }

    /**
     * 加载原始图像
     *
     * @param context 上下文
     * @param url url
     * @param loadImageResult 加载图像结果
     * @param executor 遗嘱执行人
     */
    public static void loadOriginalImage(Context context, String url,
                                         IResult<PixelMap> loadImageResult, Executor executor) {
        if (TextUtils.isEmpty(url)) {
            return;
        }
        Uri uri = Uri.parse(url);
        ImagePipeline imagePipeline = Fresco.getImagePipeline();
        ImageRequestBuilder builder = ImageRequestBuilder.newBuilderWithSource(uri);
        ImageRequest imageRequest = builder.build();
        DataSource<CloseableReference<CloseableImage>> dataSource = imagePipeline // 获取已解码的图片，返回的是Bitmap
            .fetchDecodedImage(imageRequest, context);
        dataSource.subscribe(new BaseDataSubscriber<CloseableReference<CloseableImage>>() {
            @Override
            public void onNewResultImpl(DataSource<CloseableReference<CloseableImage>> dataSource) {
                if (!dataSource.isFinished()) {
                    return;
                }
                CloseableReference<CloseableImage> imageReference = dataSource.getResult();
                disposePixelMap(imageReference, loadImageResult);
            }

            @Override
            public void onFailureImpl(DataSource dataSource) {
                if (loadImageResult != null) {
                    loadImageResult.onResult(null);
                }

                Throwable throwable = dataSource.getFailureCause();
                if (throwable != null) {
                    MLog.error("ImageLoader", "onFailureImpl = " + throwable.toString());
                }
            }
        }, executor);
    }

    private static void disposePixelMap(CloseableReference<CloseableImage> imageReference,
                                        IResult<PixelMap> loadImageResult) {
        if (imageReference != null) {
            CloseableReference<CloseableImage> closeableReference = imageReference.clone();
            try {
                setPixelMap(closeableReference, loadImageResult);
            } finally {
                imageReference.close();
                closeableReference.close();
            }
        }
    }

    private static void setPixelMap(CloseableReference<CloseableImage> closeableReference,
                                    IResult<PixelMap> loadImageResult) {
        CloseableImage closeableImage = closeableReference.get();
        if (closeableImage instanceof CloseableAnimatedImage) {
            AnimatedImageResult animatedImageResult = ((CloseableAnimatedImage) closeableImage).getImageResult();
            if (animatedImageResult != null && animatedImageResult.getImage() != null) {
                int imageWidth = animatedImageResult.getImage().getWidth();
                int imageHeight = animatedImageResult.getImage().getHeight();

                ImageSource.DecodingOptions options = new ImageSource.DecodingOptions();
                options.desiredSize.width = imageWidth;
                options.desiredSize.height = imageHeight;
                options.desiredPixelFormat = PixelFormat.ARGB_8888;
                ImageSource imageSource = ImageSource.createIncrementalSource(new ImageSource.SourceOptions());
                PixelMap bitmap = imageSource.createPixelmap(options);
                animatedImageResult.getImage().getFrame(0).renderFrame(imageWidth, imageHeight, bitmap);
                if (loadImageResult != null) {
                    loadImageResult.onResult(bitmap);
                }
            }
        } else if (closeableImage instanceof CloseableBitmap) {
            CloseableBitmap closeableBitmap = (CloseableBitmap) closeableImage;
            PixelMap bitmap = closeableBitmap.getUnderlyingBitmap();
            if (bitmap != null && !bitmap.isReleased()) {
                PixelMap tempBitmap = PixelMap.create(bitmap, new PixelMap.InitializationOptions());
                if (loadImageResult != null) {
                    loadImageResult.onResult(tempBitmap);
                }
            }
        }
    }

    /**
     * 下载图片
     *
     * @param context 上下文
     * @param url url
     * @param loadFileResult 加载文件的结果
     */
    public static void downloadImage(Context context, String url, IDownloadResult loadFileResult) {
        if (TextUtils.isEmpty(url)) {
            return;
        }
        Uri uri = Uri.parse(url);
        ImagePipeline imagePipeline = Fresco.getImagePipeline();
        ImageRequestBuilder builder = ImageRequestBuilder.newBuilderWithSource(uri);
        ImageRequest imageRequest = builder.build();
        DataSource<CloseableReference<PooledByteBuffer>> dataSource = imagePipeline // 获取未解码的图片数据
            .fetchEncodedImage(imageRequest, context);
        dataSource.subscribe(new BaseDataSubscriber<CloseableReference<PooledByteBuffer>>() {
            @Override
            public void onNewResultImpl(DataSource<CloseableReference<PooledByteBuffer>> dataSource) {
                if (!dataSource.isFinished() || loadFileResult == null) {
                    return;
                }
                closeablePixelMap(dataSource, loadFileResult);
            }

            @Override
            public void onProgressUpdate(DataSource<CloseableReference<PooledByteBuffer>> dataSource) {
                int progress = (int) (dataSource.getProgress() * 100);
                if (loadFileResult != null) {
                    loadFileResult.onProgress(progress);
                }
            }

            @Override
            public void onFailureImpl(DataSource dataSource) {
                if (loadFileResult != null) {
                    loadFileResult.onResult(null);
                }

                Throwable throwable = dataSource.getFailureCause();
                if (throwable != null) {
                    MLog.error("ImageLoader", "onFailureImpl = " + throwable.toString());
                }
            }
        }, Executors.newSingleThreadExecutor());
    }

    private static void closeablePixelMap(DataSource<CloseableReference<PooledByteBuffer>> dataSource,
                                          IDownloadResult loadFileResult) {
        CloseableReference<PooledByteBuffer> imageReference = dataSource.getResult();
        if (imageReference != null) {
            CloseableReference<PooledByteBuffer> closeableReference = imageReference.clone();
            try {
                PooledByteBuffer pooledByteBuffer = closeableReference.get();
                InputStream inputStream = new PooledByteBufferInputStream(pooledByteBuffer);
                String photoPath = loadFileResult.getFilePath();
                byte[] data = StreamTool.read(inputStream);
                StreamTool.write(photoPath, data);
                loadFileResult.onResult(photoPath);
            } catch (IOException error) {
                loadFileResult.onResult(null);
                MLog.error("downloadImage IOException " + error.getLocalizedMessage());
            } finally {
                imageReference.close();
                closeableReference.close();
            }
        }
    }

    /**
     * 加载本地磁盘缓存
     *
     * @param context 上下文
     * @param url url
     * @param loadImageResult 加载图像结果
     */
    public static void loadLocalDiskCache(Context context, String url, IResult<PixelMap> loadImageResult) {
        if (TextUtils.isEmpty(url)) {
            return;
        }
        ImageRequest imageRequest = ImageRequestBuilder.newBuilderWithSource(Uri.parse(url)).build();
        ImagePipeline imagePipeline = Fresco.getImagePipeline();
        DataSource<CloseableReference<CloseableImage>> dataSource = imagePipeline // 获取已解码的图片，返回的是Bitmap
            .fetchDecodedImage(imageRequest, context,
                ImageRequest.RequestLevel.DISK_CACHE);
        dataSource.subscribe(new BaseDataSubscriber<CloseableReference<CloseableImage>>() {
            @Override
            public void onNewResultImpl(DataSource<CloseableReference<CloseableImage>> dataSource) {
                if (!dataSource.isFinished()) {
                    return;
                }

                loadLocalDiskPixelMap(dataSource, loadImageResult);
            }

            @Override
            public void onFailureImpl(DataSource dataSource) {
                if (loadImageResult != null) {
                    loadImageResult.onResult(null);
                }

                Throwable throwable = dataSource.getFailureCause();
                if (throwable != null) {
                    MLog.error("ImageLoader", "onFailureImpl = " + throwable.toString());
                }
            }
        }, UiThreadImmediateExecutorService.getInstance());
    }

    private static void loadLocalDiskPixelMap(DataSource<CloseableReference<CloseableImage>> dataSource,
                                              IResult<PixelMap> loadImageResult) {
        CloseableReference<CloseableImage> imageReference = dataSource.getResult();
        if (imageReference != null) {
            CloseableReference<CloseableImage> closeableReference = imageReference.clone();
            try {
                setPixelMap3(loadImageResult, closeableReference);
            } finally {
                imageReference.close();
                closeableReference.close();
            }
        }
    }

    private static void setPixelMap3(IResult<PixelMap> loadImageResult,
                                     CloseableReference<CloseableImage> closeableReference) {
        CloseableImage closeableImage = closeableReference.get();
        if (closeableImage instanceof CloseableAnimatedImage) {
            AnimatedImageResult animatedImageResult = ((CloseableAnimatedImage) closeableImage).getImageResult();
            if (animatedImageResult != null && animatedImageResult.getImage() != null) {
                int imageWidth = animatedImageResult.getImage().getWidth();
                int imageHeight = animatedImageResult.getImage().getHeight();

                ImageSource.DecodingOptions options = new ImageSource.DecodingOptions();
                options.desiredSize.width = imageWidth;
                options.desiredSize.height = imageHeight;
                options.desiredPixelFormat = PixelFormat.ARGB_8888;
                ImageSource imageSource = ImageSource.createIncrementalSource(new ImageSource.SourceOptions());
                PixelMap bitmap = imageSource.createPixelmap(options);
                animatedImageResult.getImage().getFrame(0).renderFrame(imageWidth, imageHeight, bitmap);
                if (loadImageResult != null) {
                    loadImageResult.onResult(bitmap);
                }
            }
        } else if (closeableImage instanceof CloseableBitmap) {
            CloseableBitmap closeableBitmap = (CloseableBitmap) closeableImage;
            PixelMap bitmap = closeableBitmap.getUnderlyingBitmap();
            if (bitmap != null && !bitmap.isReleased()) {
                PixelMap tempBitmap = PixelMap.create(bitmap, new PixelMap.InitializationOptions());
                if (loadImageResult != null) {
                    loadImageResult.onResult(tempBitmap);
                }
            }
        }
    }
}
